<template>
  <div class="tabs-container">
    <div class="tabs-main">
      <div class="main">
        <div ref="tabCon" class="tabs-content">
          <template v-for="(pageItem, index) in tabsList" :key="pageItem.fullPath">
            <div
              :class="activeKey == pageItem.fullPath ? 'active tabs-item' : 'tabs-item'"
              @click="changePage($event, pageItem.fullPath, index)"
            >
              <span class="title">{{ pageItem.meta.title }}</span>
              <div class="close" @click.stop="editTabItem(pageItem.fullPath)">
                <CloseCircleFilled class="close-icon" />
              </div>
            </div>
          </template>
        </div>
      </div>
      <div class="right">
        <a-dropdown :trigger="['click']">
          <a class="ant-dropdown-link" @click.prevent>
            <icon-font type="icon-xiala" size="32" style="color: #333" />
          </a>
          <template #overlay>
            <a-menu style="user-select: none">
              <a-menu-item key="1" :disabled="activeKey !== route.fullPath" @click="reloadPage">
                <ReloadOutlined />
                刷新
              </a-menu-item>
              <a-menu-item key="2" @click="removeTab(route)">
                <CloseOutlined />
                关闭
              </a-menu-item>
              <a-menu-divider />
              <a-menu-item key="5" @click="closeOther(route)">
                <ColumnWidthOutlined />
                关闭其他
              </a-menu-item>
              <a-menu-item key="6" @click="closeAll">
                <MinusOutlined />
                关闭全部
              </a-menu-item>
            </a-menu>
          </template>
        </a-dropdown>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import {
  CloseOutlined,
  CloseCircleFilled,
  CaretDownOutlined,
  ReloadOutlined,
  ColumnWidthOutlined,
  MinusOutlined,
  DoubleRightOutlined,
  DoubleLeftOutlined
} from '@ant-design/icons-vue';
import { computed, defineComponent, provide, reactive, ref, Ref, toRefs, unref, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { useStore } from '@/store';
import { storage } from '@/utils/Storage';
import { TABS_ROUTES } from '@/store/mutation-types';
import { RouteItem } from '@/store/modules/tabs-view/state';
import { message } from 'ant-design-vue';
export default defineComponent({
  components: {
    CloseOutlined,
    CloseCircleFilled,
    CaretDownOutlined,
    ReloadOutlined,
    ColumnWidthOutlined,
    MinusOutlined,
    DoubleRightOutlined,
    DoubleLeftOutlined
  },
  setup() {
    const route = useRoute();
    const router = useRouter();
    const store = useStore();

    const isClick = ref(false);

    const tabCon: Ref<HTMLDivElement | null> = ref(null);

    const lastItemIndex = ref(0);
    const itemIndex = ref(0);

    // 切换页面
    const changePage = (e, key, index) => {
      isClick.value = true;
      // 容器宽度和内部点击的 item 宽度
      let boxWidth = tabCon.value!.offsetWidth;
      let elWidth = e.target.offsetWidth;
      // 上一个选中的 item 下标 和 当前选中 item 下标
      lastItemIndex.value = itemIndex.value;
      itemIndex.value = index;
      // 将容器的滚动宽度切分为3部分
      if (elWidth <= boxWidth / 3) {
        // 获取当前容器的 scrollLeft 并计算接下去要移动的目标值
        let total = index * 70 - Math.floor(boxWidth / 3);
        tabMove(total);
        state.activeKey = key;
        router.push(key).then(() => {
          isClick.value = false;
        });
      }
    };
    /**
     *  @param distance 滚动容器的scrollLeft
     *  @param total
     *  @param step 移动的步长
     *  @description 点击tab的动画，禁止容器自带的滚动
     */
    const tabMove = (total) => {
      tabCon.value!.scrollLeft = total;
    };

    // 获取简易的路由对象
    const getSimpleRoute = (route): RouteItem => {
      const { fullPath, hash, meta, name, params, path, query } = route;
      return { fullPath, hash, meta, name, params, path, query };
    };

    let routes: RouteItem[] = [];

    try {
      const routesStr = storage.get(TABS_ROUTES) as string | null | undefined;
      routes = routesStr ? JSON.parse(routesStr) : [getSimpleRoute(route)];
    } catch (e) {
      routes = [getSimpleRoute(route)];
    }
    const state = reactive({
      activeKey: route.fullPath
    });
    // 初始化标签页
    store.commit('tabsView/initTabs', routes);

    // 移除缓存组件名称
    const delKeepAliveCompName = () => {
      if (route.meta.keepAlive) {
        const name = router.currentRoute.value.matched.find((item) => item.name == route.name)
          ?.components?.default.name;
        if (name) {
          store.state.asyncRoute.keepAliveComponents =
            store.state.asyncRoute.keepAliveComponents.filter((item) => item != name);
        }
      }
    };

    // 标签页列表
    const tabsList = computed(() => store.state.tabsView.tabsList);
    const whiteList = [
      'Redirect',
      'loading',
      'error',
      'error-404',
      'assets-detail',
      'info-detail',
      'consumable-out',
      'consumable-add',
      'assets-opear',
      'aliyun-detail',
      'network-detail',
      'aliyun-machine'
    ];

    watch(
      () => route.fullPath,
      () => {
        // 不存在的路由
        const notFondRoutes: string[] = [];
        tabsList.value.forEach((item) => {
          if (!router.hasRoute(item.name)) {
            notFondRoutes.push(item.name);
          }
        });
        if (route.fullPath.indexOf('webview') > -1) return;
        // 过滤不存在的路由
        if (notFondRoutes.length) {
          store.commit(
            'tabsView/initTabs',
            tabsList.value.filter((item) => !notFondRoutes.includes(item.name))
          );
        }
      }
    );
    const autoMove = (to) => {
      let boxWidth = tabCon.value!.offsetWidth;
      let curIndex = 0;
      tabsList.value.forEach((item, index) => {
        if (item.fullPath == to) {
          curIndex = index;
        }
      });
      let total = curIndex * 70 - Math.floor(boxWidth / 3);
      tabMove(total);
    };
    watch(
      () => route.fullPath,
      (to) => {
        if (whiteList.includes(route.name as string)) {
          state.activeKey = '';
          return;
        }
        setTimeout(() => {
          autoMove(to);
        }, 100);
        state.activeKey = to;
        // tabsViewMutations.addTabs(getSimpleRoute(route))
        store.commit('tabsView/addTabs', getSimpleRoute(route));
      },
      { immediate: true }
    );

    // 在页面关闭或刷新之前，保存数据
    window.addEventListener('beforeunload', () => {
      storage.set(TABS_ROUTES, JSON.stringify(tabsList.value));
    });

    // 关闭当前页面
    const removeTab = (route) => {
      if (tabsList.value.length === 1) {
        return message.warning('这已经是最后一页，不能再关闭了！');
      }
      delKeepAliveCompName();
      // tabsViewMutations.closeCurrentTabs(route)
      store.commit('tabsView/closeCurrentTab', route);
      // 如果关闭的是当前页
      if (state.activeKey === route.fullPath) {
        const currentRoute = tabsList.value[Math.max(0, tabsList.value.length - 1)];
        state.activeKey = currentRoute.fullPath;
        router.push(currentRoute).catch(() => true);
      }
    };
    // tabs 编辑（remove || add）
    const editTabItem = (targetKey) => {
      removeTab(tabsList.value.find((item) => item.fullPath == targetKey));
    };

    // 刷新页面
    const reloadPage = () => {
      delKeepAliveCompName();
      router
        .push({
          path: '/redirect' + unref(route).fullPath
        })
        .catch(() => true);
    };
    // 注入刷新页面方法
    provide('reloadPage', reloadPage);

    // 关闭其他
    const closeOther = (route) => {
      // tabsViewMutations.closeOtherTabs(route)
      store.commit('tabsView/closeOtherTabs', route);
      state.activeKey = route.fullPath;
      router.replace(route.fullPath);
    };

    // 关闭全部
    const closeAll = () => {
      localStorage.removeItem('routes');
      // tabsViewMutations.closeAllTabs()
      store.commit('tabsView/closeAllTabs');
      router.replace('/');
    };

    // 首页按钮
    const backIndex = () => {
      router.push('/').catch(() => true);
    };

    return {
      reloadPage,
      removeTab,
      closeOther,
      closeAll,
      route,
      editTabItem,
      changePage,
      tabsList,
      backIndex,
      tabCon,
      ...toRefs(state)
    };
  }
});
</script>

<style scoped lang="less">
.tabs-container {
  width: 100%;
  height: 54px;
  background: #fff;
  .home-page {
    width: 46px;
    height: 46px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-right: 1px solid #e5e7ed;
    cursor: pointer;
    float: left;
    img {
      width: 20px;
      height: 20px;
    }
  }
  .tabs-main {
    width: 100%;
    height: 54px;
    display: flex;
    align-items: center;
    justify-content: center;
    float: left;
    .main {
      width: calc(~'100% - 40px');
      height: 54px;
      display: flex;
      align-items: center;
      justify-content: center;
      .tab-left,
      .tab-right {
        width: 40px;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
      }
      .tabs-content {
        flex: 1;
        height: 100%;
        overflow-x: auto;
        display: flex;
        align-items: flex-start;
        justify-content: flex-start;
        padding: 5px 10px 0 10px;
        box-sizing: border-box;
        &::-webkit-scrollbar {
          display: none;
        }
        .tabs-item {
          // width: 80px;
          padding: 8px 20px;
          margin-right: 2px;
          text-align: center;
          float: left;
          display: flex;
          align-items: center;
          justify-content: center;
          font-size: 14px;
          font-family: MicrosoftYaHei;
          color: #666;
          background: #fafafa;
          transition: background 0.5s;
          border: 1px solid #fafafa;
          cursor: pointer;
          &:last-of-type {
            margin: 0;
          }
          .title {
            white-space: nowrap;
          }
          .close {
            width: 0;
            overflow: hidden;
            height: 100%;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.2s;
            .close-icon {
              transition: all 0.2s;
              opacity: 0;
              color: #ccc;
              &:hover {
                color: #f00;
              }
            }
          }
          &:hover {
            .close {
              width: 20px;
              margin-left: 1px;
            }
            .close-icon {
              opacity: 1;
            }
          }
          &.active {
            background: #fff;
            color: #1890ff;
            border-radius: 4px 4px 0px 0px;
            border: 1px solid #ebebe8;
            border-bottom: none;
          }
        }
      }
    }
    .right {
      width: 40px;
      height: 40px;
      display: flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
    }
  }
}
</style>
